/**
 * Copyright (C) 2006-2013 phloc systems
 * http://www.phloc.com
 * office[at]phloc[dot]com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.phloc.genericode;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.ValidationEventHandler;

import com.phloc.commons.annotations.Nonempty;
import com.phloc.commons.annotations.OverrideOnDemand;
import com.phloc.commons.io.IReadableResource;
import com.phloc.commons.jaxb.JAXBContextCache;
import com.phloc.commons.jaxb.validation.LoggingValidationEventHandler;
import com.phloc.commons.xml.schema.XMLSchemaCache;

/**
 * Abstract reader and writer for Genericode documents.
 * 
 * @author philip
 */
@Deprecated
public abstract class AbstractGenericodeMarshaller
{
  protected AbstractGenericodeMarshaller ()
  {}

  /**
   * Create the JAXB validation event handler to be used for marshalling and
   * unmarshalling.
   * 
   * @param aOriginalEventHandler
   *        the original event handler from the marshaller/unmarshaller
   * @return <code>null</code> to indicate that no specific event handler is
   *         needed
   */
  @OverrideOnDemand
  @Nullable
  protected ValidationEventHandler createValidationEventHandler (final ValidationEventHandler aOriginalEventHandler)
  {
    return new LoggingValidationEventHandler (aOriginalEventHandler);
  }

  /**
   * Should the {@link JAXBContextCache} be used? Since creating the JAXB
   * context is quite cost intensive this is recommended.
   * 
   * @return <code>true</code> if the {@link JAXBContextCache} should be used,
   *         <code>false</code> otherwise. It's <code>true</code> by default.
   */
  @OverrideOnDemand
  protected boolean useJAXContextCache ()
  {
    return true;
  }

  @Nonnull
  protected final Unmarshaller createUnmarshaller (@Nonnull final Class <?> aMainClass,
                                                   @Nonnull @Nonempty final IReadableResource [] aXSDs) throws JAXBException
  {
    // Since creating the JAXB context is quite cost intensive this is done
    // only once!
    final JAXBContext aJAXBContext = useJAXContextCache () ? JAXBContextCache.getInstance ()
                                                                             .getFromCache (aMainClass.getPackage ())
                                                          : JAXBContext.newInstance (aMainClass.getPackage ()
                                                                                               .getName ());

    // create an Unmarshaller
    final Unmarshaller aUnmarshaller = aJAXBContext.createUnmarshaller ();
    aUnmarshaller.setEventHandler (createValidationEventHandler (aUnmarshaller.getEventHandler ()));

    // Validating!
    aUnmarshaller.setSchema (XMLSchemaCache.getInstance ().getSchema (aXSDs));
    return aUnmarshaller;
  }

  @Nonnull
  protected final Marshaller createMarshaller (@Nonnull final Class <?> aMainClass,
                                               @Nonnull @Nonempty final IReadableResource [] aXSDs) throws JAXBException
  {
    final JAXBContext aJAXBContext = useJAXContextCache () ? JAXBContextCache.getInstance ()
                                                                             .getFromCache (aMainClass.getPackage ())
                                                          : JAXBContext.newInstance (aMainClass.getPackage ()
                                                                                               .getName ());

    // create an Unmarshaller
    final Marshaller aMarshaller = aJAXBContext.createMarshaller ();
    aMarshaller.setEventHandler (createValidationEventHandler (aMarshaller.getEventHandler ()));

    // Validating!
    aMarshaller.setSchema (XMLSchemaCache.getInstance ().getSchema (aXSDs));

    return aMarshaller;
  }
}
